package org.geektimes.rest.client;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.Map;

public class DefaultClient implements Client {
    /**
     * Close client instance and all it's associated resources. Subsequent calls
     * have no effect and are ignored. Once the client is closed, invoking any
     * other method on the client instance would result in an {@link IllegalStateException}
     * being thrown.
     * <p/>
     * Calling this method effectively invalidates all {@link WebTarget resource targets}
     * produced by the client instance. Invoking any method on such targets once the client
     * is closed would result in an {@link IllegalStateException} being thrown.
     */
    @Override
    public void close() {

    }

    /**
     * Build a new web resource target.
     *
     * @param uri web resource URI. May contain template parameters. Must not be {@code null}.
     * @return web resource target bound to the provided URI.
     * @throws IllegalArgumentException in case the supplied string is not a valid URI template.
     * @throws NullPointerException     in case the supplied argument is {@code null}.
     */
    @Override
    public WebTarget target(String uri) {
        return target(URI.create(uri));
    }

    /**
     * Build a new web resource target.
     *
     * @param uri web resource URI. Must not be {@code null}.
     * @return web resource target bound to the provided URI.
     * @throws NullPointerException in case the supplied argument is {@code null}.
     */
    @Override
    public WebTarget target(URI uri) {
        return target(UriBuilder.fromUri(uri));
    }

    /**
     * Build a new web resource target.
     *
     * @param uriBuilder web resource URI represented as URI builder. Must not be {@code null}.
     * @return web resource target bound to the provided URI.
     * @throws NullPointerException in case the supplied argument is {@code null}.
     */
    @Override
    public WebTarget target(UriBuilder uriBuilder) {
        return new ImmutableWebTarget(uriBuilder);
    }

    /**
     * Build a new web resource target.
     *
     * @param link link to a web resource. Must not be {@code null}.
     * @return web resource target bound to the linked web resource.
     * @throws NullPointerException in case the supplied argument is {@code null}.
     */
    @Override
    public WebTarget target(Link link) {
        return target(link.getUriBuilder());
    }

    /**
     * <p>Build an invocation builder from a link. It uses the URI and the type
     * of the link to initialize the invocation builder. The type is used as the
     * initial value for the HTTP Accept header, if present.</p>
     *
     * @param link link to build invocation from. Must not be {@code null}.
     * @return newly created invocation builder.
     * @throws NullPointerException in case link is {@code null}.
     */
    @Override
    public Invocation.Builder invocation(Link link) {
        return null;
    }

    /**
     * Get the SSL context configured to be used with the current client run-time.
     *
     * @return SSL context configured to be used with the current client run-time.
     */
    @Override
    public SSLContext getSslContext() {
        return null;
    }

    /**
     * Get the hostname verifier configured in the client or {@code null} in case
     * no hostname verifier has been configured.
     *
     * @return client hostname verifier or {@code null} if not set.
     */
    @Override
    public HostnameVerifier getHostnameVerifier() {
        return null;
    }

    /**
     * Get a live view of an internal configuration state of this configurable instance.
     * <p>
     * Any changes made using methods of this {@code Configurable} instance will be reflected
     * in the returned {@code Configuration} instance.
     * <p>
     * The returned {@code Configuration} instance and the collection data it provides are not
     * thread-safe wrt. modification made using methods on the parent configurable object.
     * </p>
     *
     * @return configuration live view of the internal configuration state.
     */
    @Override
    public Configuration getConfiguration() {
        return null;
    }

    /**
     * Set the new configuration property, if already set, the existing value of
     * the property will be updated. Setting a {@code null} value into a property
     * effectively removes the property from the property bag.
     *
     * @param name  property name.
     * @param value (new) property value. {@code null} value removes the property
     *              with the given name.
     * @return the updated configurable instance.
     */
    @Override
    public Client property(String name, Object value) {
        return null;
    }

    /**
     * Register a class of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * Implementations SHOULD warn about and ignore registrations that do not
     * conform to the requirements of supported JAX-RS component types in the
     * given configurable context. Any subsequent registration attempts for a component
     * type, for which a class or instance-based registration already exists in the system
     * MUST be rejected by the JAX-RS implementation and a warning SHOULD be raised to
     * inform the user about the rejected registration.
     * <p>
     * The registered JAX-RS component class is registered as a contract provider of
     * all the recognized JAX-RS or implementation-specific extension contracts including
     * meta-provider contracts, such as {@code Feature} or {@link DynamicFeature}.
     * <p>
     * As opposed to component instances registered via {@link #register(Object)} method,
     * the lifecycle of components registered using this class-based {@code register(...)}
     * method is fully managed by the JAX-RS implementation or any underlying IoC
     * container supported by the implementation.
     * </p>
     *
     * @param componentClass JAX-RS component class to be configured in the scope of this
     *                       configurable context.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Class<?> componentClass) {
        return null;
    }

    /**
     * Register a class of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides the same functionality as {@link #register(Class)}
     * except that any priority specified on the registered JAX-RS component class via
     * {@code javax.annotation.Priority} annotation is overridden with the supplied
     * {@code priority} value.
     * </p>
     * <p>
     * Note that in case the priority is not applicable to a particular
     * provider contract implemented by the class of the registered component, the supplied
     * {@code priority} value will be ignored for that contract.
     * </p>
     *
     * @param componentClass JAX-RS component class to be configured in the scope of this
     *                       configurable context.
     * @param priority       the overriding priority for the registered component
     *                       and all the provider contracts the component implements.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Class<?> componentClass, int priority) {
        return null;
    }

    /**
     * Register a class of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides the same functionality as {@link #register(Class)}
     * except the JAX-RS component class is only registered as a provider of the listed
     * extension provider or meta-provider {@code contracts}.
     * All explicitly enumerated contract types must represent a class or an interface
     * implemented or extended by the registered component. Contracts that are not
     * {@link Class#isAssignableFrom(Class) assignable from} the registered component class
     * MUST be ignored and implementations SHOULD raise a warning to inform users about the
     * ignored contract(s).
     * </p>
     *
     * @param componentClass JAX-RS component class to be configured in the scope of this
     *                       configurable context.
     * @param contracts      the specific extension provider or meta-provider contracts
     *                       implemented by the component for which the component should
     *                       be registered.
     *                       Implementations MUST ignore attempts to register a component
     *                       class for an empty or {@code null} collection of contracts via
     *                       this method and SHOULD raise a warning about such event.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Class<?> componentClass, Class<?>... contracts) {
        return null;
    }

    /**
     * Register a class of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides same functionality as {@link #register(Class, Class[])}
     * except that any priority specified on the registered JAX-RS component class via
     * {@code javax.annotation.Priority} annotation is overridden
     * for each extension provider contract type separately with an integer priority value
     * specified as a value in the supplied map of [contract type, priority] pairs.
     * </p>
     * <p>
     * Note that in case a priority is not applicable to a provider contract registered
     * for the JAX-RS component, the supplied priority value is ignored for such
     * contract.
     * </p>
     *
     * @param componentClass JAX-RS component class to be configured in the scope of this
     *                       configurable context.
     * @param contracts      map of the specific extension provider and meta-provider contracts
     *                       and their associated priorities for which the JAX-RS component
     *                       is registered.
     *                       All contracts in the map must represent a class or an interface
     *                       implemented or extended by the JAX-RS component. Contracts that are
     *                       not {@link Class#isAssignableFrom(Class) assignable from} the registered
     *                       component class MUST be ignored and implementations SHOULD raise a warning
     *                       to inform users about the ignored contract(s).
     * @return the updated configurable context.
     */
    @Override
    public Client register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
        return null;
    }

    /**
     * Register an instance of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * Implementations SHOULD warn about and ignore registrations that do not
     * conform to the requirements of supported JAX-RS component types in the
     * given configurable context. Any subsequent registration attempts for a component
     * type, for which a class or instance-based registration already exists in the system
     * MUST be rejected by the JAX-RS implementation and a warning SHOULD be raised to
     * inform the user about the rejected registration.
     * <p>
     * The registered JAX-RS component is registered as a contract provider of
     * all the recognized JAX-RS or implementation-specific extension contracts including
     * meta-provider contracts, such as {@code Feature} or {@link DynamicFeature}.
     * <p>
     * As opposed to components registered via {@link #register(Class)} method,
     * the lifecycle of providers registered using this instance-based {@code register(...)}
     * is not managed by JAX-RS runtime. The same registered component instance is used during
     * the whole lifespan of the configurable context.
     * Fields and properties of all registered JAX-RS component instances are injected with their
     * declared dependencies (see {@link Context}) by the JAX-RS runtime prior to use.
     * </p>
     *
     * @param component JAX-RS component instance to be configured in the scope of this
     *                  configurable context.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Object component) {
        return null;
    }

    /**
     * Register an instance of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides the same functionality as {@link #register(Object)}
     * except that any priority specified on the registered JAX-RS component class via
     * {@code javax.annotation.Priority} annotation is overridden with the supplied
     * {@code priority} value.
     * </p>
     * <p>
     * Note that in case the priority is not applicable to a particular
     * provider contract implemented by the class of the registered component, the supplied
     * {@code priority} value will be ignored for that contract.
     * </p>
     *
     * @param component JAX-RS component instance to be configured in the scope of this
     *                  configurable context.
     * @param priority  the overriding priority for the registered component
     *                  and all the provider contracts the component implements.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Object component, int priority) {
        return null;
    }

    /**
     * Register an instance of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides the same functionality as {@link #register(Object)}
     * except the JAX-RS component class is only registered as a provider of the listed
     * extension provider or meta-provider {@code contracts}.
     * All explicitly enumerated contract types must represent a class or an interface
     * implemented or extended by the registered component. Contracts that are not
     * {@link Class#isAssignableFrom(Class) assignable from} the registered component class
     * MUST be ignored and implementations SHOULD raise a warning to inform users about the
     * ignored contract(s).
     * </p>
     *
     * @param component JAX-RS component instance to be configured in the scope of this
     *                  configurable context.
     * @param contracts the specific extension provider or meta-provider contracts
     *                  implemented by the component for which the component should
     *                  be registered.
     *                  Implementations MUST ignore attempts to register a component
     *                  class for an empty or {@code null} collection of contracts via
     *                  this method and SHOULD raise a warning about such event.
     * @return the updated configurable context.
     */
    @Override
    public Client register(Object component, Class<?>... contracts) {
        return null;
    }

    /**
     * Register an instance of a custom JAX-RS component (such as an extension provider or
     * a {@link Feature feature} meta-provider) to be instantiated
     * and used in the scope of this configurable context.
     * <p>
     * This registration method provides same functionality as {@link #register(Object, Class[])}
     * except that any priority specified on the registered JAX-RS component class via
     * {@code javax.annotation.Priority} annotation is overridden
     * for each extension provider contract type separately with an integer priority value
     * specified as a value in the supplied map of [contract type, priority] pairs.
     * </p>
     * <p>
     * Note that in case a priority is not applicable to a provider contract registered
     * for the JAX-RS component, the supplied priority value is ignored for such
     * contract.
     * </p>
     *
     * @param component JAX-RS component instance to be configured in the scope of this
     *                  configurable context.
     * @param contracts map of the specific extension provider and meta-provider contracts
     *                  and their associated priorities for which the JAX-RS component
     *                  is registered.
     *                  All contracts in the map must represent a class or an interface
     *                  implemented or extended by the JAX-RS component. Contracts that are
     *                  not {@link Class#isAssignableFrom(Class) assignable from} the registered
     *                  component class MUST be ignored and implementations SHOULD raise a warning
     *                  to inform users about the ignored contract(s).
     * @return the updated configurable context.
     */
    @Override
    public Client register(Object component, Map<Class<?>, Integer> contracts) {
        return null;
    }
}
